package com.livi.security.config.security;

import java.util.Collection;
import java.util.Iterator;

import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;

/**
 * @Description: 自定义权限决策管理器。 有了权限资源，知道了当前访问的url需要的具体权限，接下来就是决策当前的访问是否能通过权限验证了
 **/
@Component
public class CustomAccessDecisionManager implements AccessDecisionManager {

	/**
	 * @Description: 取当前用户的权限与这次请求的这个url需要的权限作对比，决定是否放行 auth
	 *               包含了当前的用户信息，包括拥有的权限,即之前UserDetailsService登录时候存储的用户对象 object
	 *               就是FilterInvocation对象，可以得到request等web资源。 configAttributes
	 *               是本次访问需要的权限。即上一步的 PermissionFilter 中查询核对得到的权限列表
	 **/
	@Override
	public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)
			throws AccessDeniedException, InsufficientAuthenticationException {
		Iterator<ConfigAttribute> iterator = configAttributes.iterator();
		while (iterator.hasNext()) {
			ConfigAttribute ca = iterator.next();
			// 当前请求需要的权限
			String needRole = ca.getAttribute();
			needRole = needRole.split("\\?")[0];
			// 当前用户所具有的权限
			Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
			for (GrantedAuthority authority : authorities) {
				if (authority.getAuthority().equals(needRole)) {
					return;
				}
			}
		}
		throw new AccessDeniedException("权限不足!");
	}

	@Override
	public boolean supports(ConfigAttribute attribute) {
		return true;
	}

	@Override
	public boolean supports(Class<?> clazz) {
		return true;
	}

}
